package com.yorick.common.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.yorick.authority.entitys.ResourceDto;
import com.yorick.authority.enums.Account;
import com.yorick.common.dao.SecurityMapper;
import com.yorick.common.enums.AuthEnum;
import com.yorick.common.util.ResponseWriter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.web.util.AntPathRequestMatcher;
import org.springframework.security.web.util.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @program: AuthorityInterceptor
 * @description: 菜单拦截器
 * @author: Yorick
 * @create: 31/5/2022
 **/
@Slf4j
@Component
public class AuthorityInterceptor implements HandlerInterceptor {

    private RequestMatcher requestMatcher;

    @Resource
    SecurityMapper securityDao;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        log.info(httpServletRequest.getRequestURI());
        JSONObject allAuth = this.loadAllAuth(httpServletRequest);
        List<String> userAuth = this.loadUserAuth(httpServletRequest);
        Gson gson = new Gson();
        Set set = gson.fromJson(allAuth.toJSONString(), Map.class).entrySet();
        Iterator i = set.iterator();
        while (i.hasNext()) {
            Map.Entry<String, String> entry1 = (Map.Entry<String, String>) i.next();
            requestMatcher = new AntPathRequestMatcher(entry1.getKey());
            if (requestMatcher.matches(httpServletRequest)) {
                for (String ua : userAuth) {
                    if (ua.equals(entry1.getValue())) {
                        return true;
                    }
                }
            }
        }
        JSONObject result = new JSONObject();
        result.put("flag", "0");
        result.put("msg", "你无权访问");
        ResponseWriter.responseOutWithJson(httpServletResponse, result);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    protected JSONObject loadAllAuth(HttpServletRequest httpServletRequest) {
        HttpSession session = httpServletRequest.getSession();
        if (Objects.isNull(session.getAttribute(AuthEnum.allResource.name()))) {
            List<ResourceDto> resources = securityDao.getAuthorityNames();
            JSONObject authMap = new JSONObject();
            resources.parallelStream().forEach(
                    resource -> {
                        authMap.put(resource.getResourceString(), resource.getResourceName());
                    }
            );
            session.setAttribute(AuthEnum.allResource.name(), authMap);
            return authMap;
        } else {
            Gson gson = new Gson();
            return gson.fromJson(JSON.toJSONString(session.getAttribute(AuthEnum.allResource.name())), JSONObject.class);
        }
    }

    protected List<String> loadUserAuth(HttpServletRequest httpServletRequest) {
        HttpSession session = httpServletRequest.getSession();
        if (Objects.isNull(session.getAttribute(AuthEnum.userResource.name()))) {
            List<String> userAuthority = new ArrayList<>();
            if (Objects.nonNull(session.getAttribute(Account.account.toString()))) {
                userAuthority = securityDao.getUserAuthority(session.getAttribute(Account.account.toString()).toString());
                session.setAttribute(AuthEnum.userResource.name(), userAuthority);
            }
            return userAuthority;
        } else {
            Gson gson = new Gson();
            return gson.fromJson(session.getAttribute(AuthEnum.userResource.name()).toString(), List.class);
        }
    }
}
